package com.github.utils;

import com.github.exceptions.TimeMatchFormatException;
import com.github.utils.expand.MethodType;
import org.apache.commons.lang.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import static java.lang.Long.parseLong;

/**
 * <p> java 反射相关的工具类 </p>
 * @author  Crab2Died
 */
public class ReflexUtils {

    /**
     * <p>根据java对象属性{@link java.lang.reflect.Field}获取该属性的getter或setter方法名，
     * 另对{@link boolean}及{@link java.lang.Boolean}做了行管处理</p>
     * @author  Crab2Died
     *
     * @param field      对象属性
     * @param methodType 方法类型，getter或setter枚举
     * @return {@link String}        getter或setter方法名
     */
    static
    public String getOrSet(Field field, MethodType methodType) {

        if (null == field)
            return null;

        String fieldName = field.getName();

        // 对boolean类型的特殊处理
        if (boolean.class == field.getType()) {
            if (MethodType.SET == methodType) {
                if (fieldName.startsWith("is") &&
                        Character.isUpperCase(fieldName.substring(2, 3).toCharArray()[0])) {
                    return methodType.getValue() + fieldName.substring(2);
                }
            }
            if (MethodType.GET == methodType) {
                if (fieldName.startsWith("is") &&
                        Character.isUpperCase(fieldName.substring(2, 3).toCharArray()[0])) {
                    return fieldName;
                } else {
                    return "is" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
                }
            }
        }
        // 对Boolean类型的特殊处理
        if (Boolean.class == field.getType()) {
            if (MethodType.SET == methodType) {
                if (fieldName.startsWith("is") &&
                        Character.isUpperCase(fieldName.substring(2, 3).toCharArray()[0])) {
                    return methodType.getValue() + fieldName.substring(2);
                }
            }
            if (MethodType.GET == methodType) {
                if (fieldName.startsWith("is") &&
                        Character.isUpperCase(fieldName.substring(2, 3).toCharArray()[0])) {
                    return methodType.getValue() + fieldName.substring(2);
                }
            }
        }
        return methodType.getValue() + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
    }


    /**
     * <p>根据对象的属性名{@code fieldName}获取某个java的属性{@link java.lang.reflect.Field}</p>
     * @author  Crab2Died
     *
     * @param clazz     java对象的class属性
     * @param fieldName 属性名
     * @return {@link java.lang.reflect.Field}   java对象的属性
     */
    static
    public Field matchClassField(Class clazz, String fieldName) {
        List<Field> fields = new ArrayList<>();
        for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
            fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
        }
        for (Field field : fields) {
            if (StringUtils.equals(field.getName(), fieldName)) {
                return field;
            }
        }
        return null;
    }

    /**
     * <p>获取java对象的全部属性(包含继承)</p>
     * @author  Crab2Died
     *
     * @param clazz java对象Class
     * @return 返回对象属性集合
     */
    static
    public List<Field> getFields(Class clazz) {

        List<Field> fields = new ArrayList<>();
        for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
            fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
        }
        return fields;
    }

    /**
     * <p>获取java对象的全部属性(包含继承)</p>
     * @author  Crab2Died
     *
     * @param object java对象
     * @return 返回对象属性集合
     */
    static
    public List<Field> getFields(Object object) {

        return getFields(object.getClass());
    }

    /**
     * <p>获取java对象的全部方法(包含继承)</p>
     * @author  Crab2Died
     *
     * @param clazz java对象Class
     * @return 返回对象方法集合
     */
    static
    public List<Method> getMethods(Class clazz) {
        List<Method> methods = new ArrayList<>();
        for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
            methods.addAll(Arrays.asList(clazz.getDeclaredMethods()));
        }
        return methods;
    }

    /**
     * <p>获取java对象的全部方法(包含继承)</p>
     * @author  Crab2Died
     *
     * @param object java对象
     * @return 返回对象方法集合
     */
    static
    public List<Method> getMethods(Object object) {

        return getMethods(object.getClass());
    }

    /**
     * <p>将字符串类型转换为目标类型</p>
     * @author  Crab2Died
     *
     * @param strField 带转换参数
     * @param clazz    目标类型
     * @return Object  返回对象
     * @throws ParseException,TimeMatchFormatException
     */
    @SuppressWarnings("unchecked")
    static
    public <T> T converType(String strField, Class<T> clazz) throws ParseException,
            TimeMatchFormatException {

        if (StringUtils.isEmpty(strField))
            return null;
        if ((Long.class == clazz) || (long.class == clazz)) {
            return (T) new Long(parseLong(strField));
        }
        if ((Integer.class == clazz) || (int.class == clazz)) {
            return (T) new Integer(Integer.parseInt(strField));
        }
        if ((Float.class == clazz) || (float.class == clazz)) {
            return (T) new Float(Float.parseFloat(strField));
        }
        if ((Double.class == clazz) || (double.class == clazz)) {
            return (T) new Double(Double.parseDouble(strField));
        }
        if ((Character.class == clazz) || (char.class == clazz)) {
            return (T) new Character(strField.toCharArray()[0]);
        }
        if (Date.class == clazz) {
            return (T) DateUtils.str2Date(strField);
        }
        return (T) strField;
    }

}
